Title Banner

Previous Book Contents Book Index Next

Inside Macintosh: QuickDraw GX Printing Extensions and Drivers /
Chapter 2 - Printing Extensions / Developing a Printing Extension


The Printing Message Overrides

The code that makes up your printing extension is a set of functions that override, either partially or totally, some of the printing messages that QuickDraw GX sends during the process of printing a document. The contents of the file backwash.c, which contains
the source code for the message overrides in the background picture printing extension, are shown in the QuickDraw GX sample code.

QuickDraw GX provides a default implementation of each printing message that it sends. You can augment (partially override) some printing messages, and you can replace (totally override) others. For each printing message, QuickDraw GX provides one of three kinds of default implementations, as shown in Table 2-3.
Table 2-3 Implementation types for QuickDraw GX printing messages
Message typeDefault implementation
EmptyDoes nothing, so you can provide an override of this message to insert functionality into the printing process. You can choose to partially or totally override this message.
Can be partially overriddenProvides necessary functionality, which you augment by partially overriding it. You must forward this message to other message handlers.
Can be totally overriddenProvides basic functionality, which you can either partially or totally override.

Whenever you override a QuickDraw GX printing message, you must be certain that
the declaration of your override function matches the declaration of the message. This means that the type of function return and the type of each parameter must match the types in the message declaration. The chapter "Printing Messages" shows the declaration of each printing messages.

When you partially override a printing message, you add some functionality to that provided by other message handlers, including QuickDraw GX (through its default implementation), the printer driver, and other printing extensions. You forward the message to these other handlers, as described in the section "Forwarding Messages"
on page 2-13.

When you totally override a message, you replace any functionality that is provided
by other message handlers, including the default implementation. Your total message override does not forward the message to the other handlers. This means that you must be sure to replace the functionality that is provided by the default implementation.

Although the default implementation of a message might be empty, other printing message handlers (the printer driver and other printing extensions) can also override messages, so you need to carefully consider whether or not to create a total override
of a message.

Whether or not you can totally override a message and when you need to forward a message in your implementation of a partial override is specific to each message. The reference section "Printing Messages Reference" beginning on page 4-9 in the chapter "Printing Messages" provides this information for each message.

Choosing the Messages to Override

Which messages you need to override for your printing extension depends entirely on what you want your extension to do. There are not any messages that you are required to override. Some extensions override many messages to provide their operations, and many extensions are created by overriding only a few messages. Refer to the chapter "Printing Messages" in this book for complete information about the available messages.

Forwarding Messages

Your printing extension can forward a message in its implementation of a partial override. If you are totally overriding a message, you do not forward it to other message handlers. You can forward the message either before or after performing your own actions. To forward a message to the next message handler in the message chain, use
a statement with the following format:

anErr = Forward_MessageName(arguments);
For example, the background picture printing extension overrides the GXJobPrintDialog message to add a panel to the Print dialog box. This message must be forwarded so that the default implementation can build the default dialog box and any other message handlers can add their panels to the dialog box. Listing 2-3 shows the override of the GXJobPrintDialog message from the background picture extension.

Listing 2-3 Forwarding the GXJobPrintDialog message

OSErr BWJobPrintDialog (gxDialogResult *dlogResult)
{
   OSErr err;

   err = SetupPrintPanel();
   if (!err)
      err = Forward_GXJobPrintDialog(dlogResult);
   return err;
}
This override function calls a local function named SetupPrintPanel to add items to the Print dialog box that are used for controlling the background picture extension. If that function succeeds, this version forwards the message to the next message handler, which can add its own panel. The GXJobPrintDialog message is described on page 4-84 in the chapter "Printing Messages."

Sending Messages

Your printing extension can also send a printing message to other handlers in the message chain. When you send a message, QuickDraw GX receives it and then sends it to the first message handler in the chain. To send a message, use a statement with this format:

anErr = Send_GXMessageName(arguments);
For example, to send the GXBufferData message, which is described on page 4-139
in the chapter "Printing Messages," use the following statement:

anErr = Send_GXBufferData(gxDialogResult *);
For more information on sending messages, refer to the chapter "Message Manager"
in Inside Macintosh: QuickDraw GX Environment and Utilities.

Handling Exceptions in Your Message Overrides

The code samples presented in this chapter make use of an exception-handling strategy that simplifies the job of testing for error conditions after each function call. This strategy uses three C macros, each of which branches to an error-handling statement in response to a condition.

The first macro, nrequire, branches to a label when the value of its condition argument is anything other than 0. This macro is commonly used to test the result code from a function call and branch if the function returned an error (any value other than noErr, which is 0). The syntax of the nrequire macro is

   nrequire(condition, location);
An example of using the nrequire macro is shown in Listing 2-4.

Listing 2-4 Using the nrequire macro for exception handling

   OSErr       err;
   long        count;
   short       pictRefNum;
   PicHandle   backwashPict = nil;

   err = FSpOpenDF(opFSSpec, fsCurPerm, &pictRefNum);
   nrequire(err, CouldNotOpenFile);

   err = GetEOF(pictRefNum, &count);
   nrequire(err, CouldNotGetEOF);
   count -= 512;

   err = SetFPos(pictRefNum, fsFromStart, 512);
   nrequire(err, CouldNotSetFilePos);

   ...

   
CouldNotGetEof:
CouldNotSetFilePos:
   FSClose(pictRefNum);

CouldNotOpenFile:
   return(backwashPict);
}
The function in Listing 2-4 uses the nrequire macro instead of using an if statement
to test the value of err after each call. The nrequire macro performs a branch to the specified label if the value of err is anything other than noErr. Each label that is referenced by the nrequire macro leads to a call that cleans up after the error.

A variation of the nrequire macro that is used in some functions is the require macro. This macro is exactly the same as nrequire except that it branches when its condition argument is 0 (whereas nrequire branches on anything other than 0).
The syntax of the require macro is

   require(condition, location);
A final variation of the nrequire macro that is used in some of the functions of the background picture printing extension is the nrequire_action macro. This macro works the same way as nrequire and additionally performs an action before branching. The syntax of the nrequire_action macro is

   nrequire_action(condition, location, action);
The action is performed only if the value of the condition argument is anything other than 0. The action is performed before branching to the specified label. An example of the nrequire_action macro is shown in Listing 2-5.

Listing 2-5 Using the nrequire_action macro for exception handling

   grErr = GetJobCollectionItem(&backwashConfig, nil,
                  kBackwashCollectionType, kBackwashSettingsID);
   nrequire_action((!grErr && !backwashConfig.addBackwash &&                                     backwashConfig.haveFileInfo),
                   NotAddingBackwash, grErr = noErr);
The nrequire_action call in this example assigns the value noErr to the grErr variable before branching to the NotAddingBackwash label.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
7 JUL 1996




Navigation graphic, see text links

Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help